#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import http.server
import socketserver
import json
import os
import webbrowser
import requests
from datetime import datetime, timedelta
import time
from typing import List, Dict

# 聚合数据API配置
JUHE_FLIGHT_APPKEY = "b0daee5c7cf963ae6458020601583575"

# 城市到IATA机场代码映射
CITY_TO_IATA = {
    '大连': 'DLC', '北京': 'PEK', '上海': 'PVG', '广州': 'CAN',
    '深圳': 'SZX', '成都': 'CTU', '重庆': 'CKG', '西安': 'XIY',
    '武汉': 'WUH', '南京': 'NKG', '杭州': 'HGH', '天津': 'TSN',
    '青岛': 'TAO', '厦门': 'XMN', '长沙': 'CSX', '郑州': 'CGO',
    '合肥': 'HFE', '济南': 'TNA', '福州': 'FOC', '南昌': 'KHN',
    '石家庄': 'SJW', '太原': 'TYN', '呼和浩特': 'HET', '沈阳': 'SHE',
    '长春': 'CGQ', '哈尔滨': 'HRB', '昆明': 'KMG', '贵阳': 'KWE',
    '南宁': 'NNG', '海口': 'HAK', '三亚': 'SYX', '兰州': 'LHW',
    '西宁': 'XNN', '银川': 'INC', '乌鲁木齐': 'URC', '拉萨': 'LXA'
}

# 周边城市映射
NEARBY_CITIES = {
    '大连': ['沈阳', '营口', '丹东', '鞍山'],
    '合肥': ['南京', '武汉', '郑州', '济南'],
    '北京': ['天津', '石家庄', '保定', '廊坊'],
    '上海': ['南京', '杭州', '苏州', '无锡'],
    '广州': ['深圳', '佛山', '东莞', '中山'],
    '深圳': ['广州', '东莞', '惠州', '佛山']
}

LOCAL_RAIL_DATA_PATHS = [
    # 动态扫描用，不再固定文件名
    os.path.join(os.path.dirname(__file__), 'data')
]

def load_local_rail_data() -> List[Dict]:
    """加载本地铁路数据，支持xlsx/csv。列要求：origin,destination,train_number,departure_time,arrival_time,price,transfer(optional)
    返回标准化字典列表。
    """
    data_dir = LOCAL_RAIL_DATA_PATHS[0]
    if not os.path.isdir(data_dir):
        return []
    try:
        import glob
        import pandas as pd
        files = glob.glob(os.path.join(data_dir, '*.xlsx')) + glob.glob(os.path.join(data_dir, '*.csv'))
        required_cols = {'origin','destination','train_number','departure_time','arrival_time','price'}
        all_records: List[Dict] = []
        for path in files:
            try:
                if path.endswith('.xlsx'):
                    try:
                        # 大文件直接跳过以避免阻塞启动，建议转CSV或拆分
                        try:
                            if os.path.getsize(path) > 12 * 1024 * 1024:
                                print(f"文件较大，建议转CSV以提速，已跳过: {os.path.basename(path)}")
                                continue
                        except Exception:
                            pass
                        # 先读取表头定位列
                        header_df = pd.read_excel(path, nrows=0, engine='openpyxl')
                        # 表头标准化
                        lower_cols_map = {str(c).strip().lower(): c for c in header_df.columns}
                        header_alias = {
                            'origin': ['origin','出发地','出发城市','始发地','始发站','出发站','起点站'],
                            'destination': ['destination','目的地','到达城市','到达站','终点站'],
                            'train_number': ['train_number','车次','车次号','列车号','列车编号'],
                            'departure_time': ['departure_time','出发时间','发车时间','开车时间','发时'],
                            'arrival_time': ['arrival_time','到达时间','到时'],
                            'price': ['price','票价','二等座','二等座票价','最低价','参考价'],
                            'transfer': ['transfer','中转','中转城市','换乘城市'],
                            'seat_type': ['席别','座别','座位','座位类型']
                        }
                        selected_cols = {}
                        for std, aliases in header_alias.items():
                            for alias in aliases:
                                key = alias.strip().lower()
                                if key in lower_cols_map:
                                    selected_cols[std] = lower_cols_map[key]
                                    break
                        if not required_cols.issubset(set(selected_cols.keys())):
                            print(f"列不完整，跳过: {os.path.basename(path)}")
                            continue
                        # 仅读取需要的列，并限制最大行数，避免超大文件阻塞
                        MAX_ROWS = int(os.environ.get('RAIL_MAX_ROWS', '50000'))
                        use_cols = list(selected_cols.values())
                        if 'seat_type' in selected_cols:
                            use_cols.append(selected_cols['seat_type'])
                        df = pd.read_excel(path, usecols=use_cols, nrows=MAX_ROWS, engine='openpyxl')
                    except Exception:
                        print('读取xlsx需要 openpyxl，请安装: pip install openpyxl；已跳过: ' + os.path.basename(path))
                        continue
                else:
                    # 自适应CSV编码与分隔符
                    df = None
                    for enc in ['utf-8', 'utf-8-sig', 'gbk']:
                        try:
                            df = pd.read_csv(path, encoding=enc, engine='python', sep=None)
                            print(f"CSV读取成功 {os.path.basename(path)} 编码: {enc} 行数: {len(df)}")
                            break
                        except Exception:
                            continue
                    if df is None:
                        raise RuntimeError('CSV读取失败，尝试了多种编码')
                # 表头标准化与中英映射
                col_map = {}
                for c in df.columns:
                    cl = str(c).strip().lower()
                    col_map[cl] = cl
                # 中文->标准名
                header_alias = {
                    'origin': ['origin','出发地','出发城市','始发地','始发站','出发站','起点站'],
                    'destination': ['destination','目的地','到达城市','到达站','终点站'],
                    'train_number': ['train_number','车次','车次号','列车号','列车编号'],
                    'departure_time': ['departure_time','出发时间','发车时间','开车时间','发时'],
                    'arrival_time': ['arrival_time','到达时间','到时'],
                    'price': ['price','票价','二等座','二等座票价','最低价','参考价'],
                    'transfer': ['transfer','中转','中转城市','换乘城市'],
                    'seat_type': ['席别','座别','座位','座位类型']
                }
                # 找出每个标准列在df中的真实列名
                selected_cols = {}
                lower_cols = {str(c).strip().lower(): c for c in df.columns}
                for std, aliases in header_alias.items():
                    for alias in aliases:
                        key = alias.strip().lower()
                        if key in lower_cols:
                            selected_cols[std] = lower_cols[key]
                            break
                # 检查必需列是否具备
                if not required_cols.issubset(set(selected_cols.keys())):
                    continue
                added = 0
                for _, row in df.iterrows():
                    # 优先保留二等座票价
                    if 'seat_type' in selected_cols:
                        seat = str(row.get(selected_cols['seat_type'], '')).strip()
                        if seat and ('二等' not in seat):
                            continue
                    rec = {
                        'origin': str(row.get(selected_cols['origin'], '')).strip(),
                        'destination': str(row.get(selected_cols['destination'], '')).strip(),
                        'train_number': str(row.get(selected_cols['train_number'], '')).strip(),
                        'departure_time': str(row.get(selected_cols['departure_time'], '')).strip(),
                        'arrival_time': str(row.get(selected_cols['arrival_time'], '')).strip(),
                        'price': float(row.get(selected_cols['price'], 0) or 0),
                        'transfer': ''
                    }
                    # 可选 transfer 列
                    if 'transfer' in selected_cols:
                        val = row.get(selected_cols['transfer'], '')
                        rec['transfer'] = '' if (val is None or (hasattr(pd, 'isna') and pd.isna(val))) else str(val).strip()
                    all_records.append(rec)
                    added += 1
                print(f"已加载铁路数据 {os.path.basename(path)}：{added} 行")
            except Exception as e:
                print(f"解析铁路文件失败 {os.path.basename(path)}: {e}")
        return all_records
    except Exception as e:
        print(f"扫描本地铁路目录失败: {e}")
    return []

_LOCAL_RAIL_CACHE = load_local_rail_data()
print(f"本地铁路数据加载完成：{len(_LOCAL_RAIL_CACHE)} 条")

def _norm_city(name: str) -> str:
    if not name:
        return ''
    n = str(name).strip()
    # 去除常见后缀
    for suf in ['市', '站', '南站', '北站', '东站', '西站', '火车站', '高铁站']:
        n = n.replace(suf, '')
    return n

def find_train_routes(origin: str, destination: str, date: str) -> List[Dict]:
    """基于本地铁路表，返回直达或一次中转的高铁方案（日期仅用于展示）。"""
    routes: List[Dict] = []
    if not _LOCAL_RAIL_CACHE:
        return routes
    o = _norm_city(origin)
    d = _norm_city(destination)
    # 直达
    for r in _LOCAL_RAIL_CACHE:
        ro = _norm_city(r['origin'])
        rd = _norm_city(r['destination'])
        if ro == o and rd == d and not r.get('transfer'):
            routes.append({
                'type': 'high_speed_rail',
                'origin': origin,
                'destination': destination,
                'dep_time': f"{date} {r['departure_time']}",
                'arr_time': f"{date} {r['arrival_time']}",
                'price': int(r['price']),
                'total_time': 2.0,
                'total_price': int(r['price']),
                'transfers': 0,
                'details': [{
                    'type': 'high_speed_rail',
                    'origin': origin,
                    'destination': destination,
                    'departure_time': r['departure_time'],
                    'arrival_time': r['arrival_time'],
                    'price': int(r['price']),
                    'train_number': r['train_number']
                }]
            })
    # 一次中转（如经南京）
    for r in _LOCAL_RAIL_CACHE:
        ro = _norm_city(r['origin'])
        if ro == o and r.get('transfer'):
            mid = _norm_city(r['transfer'])
            # 找到中转-终点的段
            for r2 in _LOCAL_RAIL_CACHE:
                r2o = _norm_city(r2['origin'])
                r2d = _norm_city(r2['destination'])
                if r2o == mid and r2d == d and (not r2.get('transfer')):
                    total_price = int((r['price'] or 0) + (r2['price'] or 0))
                    routes.append({
                        'type': 'high_speed_rail',
                        'origin': origin,
                        'destination': destination,
                        'dep_time': f"{date} {r['departure_time']}",
                        'arr_time': f"{date} {r2['arrival_time']}",
                        'price': total_price,
                        'total_time': 4.0,
                        'total_price': total_price,
                        'transfers': 1,
                        'details': [
                            {
                                'type': 'high_speed_rail',
                                'origin': origin,
                                'destination': mid,
                                'departure_time': r['departure_time'],
                                'arrival_time': '',
                                'price': int(r['price'] or 0),
                                'train_number': r['train_number']
                            },
                            {
                                'type': 'high_speed_rail',
                                'origin': mid,
                                'destination': destination,
                                'departure_time': '',
                                'arrival_time': r2['arrival_time'],
                                'price': int(r2['price'] or 0),
                                'train_number': r2['train_number']
                            }
                        ]
                    })
    return routes

def _parse_hours(dep: str, arr: str) -> float:
    try:
        if not dep or not arr:
            return 0.0
        from datetime import datetime as _dt
        d1 = _dt.strptime(dep.strip(), '%H:%M')
        d2 = _dt.strptime(arr.strip(), '%H:%M')
        delta = (d2 - d1).total_seconds() / 3600.0
        if delta < 0:
            delta += 24
        return round(max(0.0, delta), 1)
    except Exception:
        return 0.0

def build_flight_rail_combos(final_destination: str, date: str, flights: List[Dict]) -> List[Dict]:
    combos: List[Dict] = []
    if not _LOCAL_RAIL_CACHE:
        return combos
    fd = _norm_city(final_destination)
    for f in flights:
        try:
            # 只考虑“到附近城市”的航班作为联运的第一段
            if not f.get('is_nearby') or f.get('nearby_type') != 'destination':
                continue
            mid_city = f.get('nearby_city') or ''
            mid = _norm_city(mid_city)
            if not mid:
                continue
            # 查询中转城市 -> 最终目的地 的直达高铁
            trains = find_train_routes(mid_city, final_destination, date)
            trains = [t for t in trains if t.get('transfers', 0) == 0 and t.get('type') == 'high_speed_rail']
            if not trains:
                continue
            # 选一条价格最低的高铁段
            trains.sort(key=lambda t: t.get('total_price', t.get('price', 0)))
            t = trains[0]
            train_detail = t['details'][0] if t.get('details') else {}
            # 计算总价与总时间（粗略相加）
            total_price = int((f.get('total_price') or f.get('price') or 0) + (t.get('total_price') or t.get('price') or 0))
            flight_time = f.get('total_time') or _parse_hours(str(f.get('dep_time',''))[-5:], str(f.get('arr_time',''))[-5:])
            train_time = t.get('total_time') or _parse_hours(train_detail.get('departure_time',''), train_detail.get('arrival_time',''))
            total_time = round((flight_time or 0) + (train_time or 0), 1)
            combos.append({
                'type': 'multimodal',
                'origin': f.get('origin'),
                'destination': final_destination,
                'dep_time': f.get('dep_time'),
                'arr_time': t.get('arr_time'),
                'total_price': total_price,
                'total_time': total_time,
                'transfers': 1,
                'details': [
                    {
                        'type': 'flight',
                        'origin': f.get('origin'),
                        'destination': mid_city,
                        'departure_time': str(f.get('dep_time',''))[-5:],
                        'arrival_time': str(f.get('arr_time',''))[-5:],
                        'price': int(f.get('total_price') or f.get('price') or 0),
                        'airline': f.get('airline'),
                        'flight_number': f.get('flight_number')
                    },
                    {
                        'type': 'high_speed_rail',
                        'origin': mid_city,
                        'destination': final_destination,
                        'departure_time': train_detail.get('departure_time',''),
                        'arrival_time': train_detail.get('arrival_time',''),
                        'price': int(t.get('total_price') or t.get('price') or 0),
                        'train_number': train_detail.get('train_number','')
                    }
                ]
            })
        except Exception as e:
            print(f"构建联运失败: {e}")
            continue
    return combos

def http_get_with_retry(url, params, timeout_seconds=25, max_retries=2):
    session = requests.Session()
    last_exc = None
    for attempt in range(max_retries + 1):
        try:
            resp = session.get(url, params=params, timeout=timeout_seconds)
            return resp
        except Exception as e:
            last_exc = e
            backoff = 1.5 ** attempt
            print(f"⚠️ 航班API请求失败，第{attempt+1}次：{e}，{('重试中' if attempt < max_retries else '不再重试')}…")
            if attempt < max_retries:
                time.sleep(backoff)
    raise last_exc


def get_flight_data(origin, destination, date):
    """获取机票数据"""
    try:
        dep_code = CITY_TO_IATA.get(origin, origin)
        arr_code = CITY_TO_IATA.get(destination, destination)
        
        url = "https://apis.juhe.cn/flight/query"
        params = {
            'key': JUHE_FLIGHT_APPKEY,
            'dtype': 'json',
            'departure': dep_code,
            'arrival': arr_code,
            'departureDate': date
        }
        
        print(f"📡 机票API请求: {url}")
        print(f"📋 参数: {params}")
        
        try:
            response = http_get_with_retry(url, params=params, timeout_seconds=25, max_retries=2)
        except Exception as e:
            print(f"❌ 航班API连续失败: {e}")
            # 兜底：返回一条可用的示例航班，避免前端空白
            fallback = [{
                'type': 'flight',
                'flight_number': 'DEMO001',
                'airline': '示例航空',
                'origin': origin,
                'destination': destination,
                'dep_time': f"{date or ''} 09:00",
                'arr_time': f"{date or ''} 11:00",
                'price': 680,
                'dep_airport': f"{origin}机场",
                'arr_airport': f"{destination}机场",
                'duration': '09:00 - 11:00',
                'source': 'fallback',
                'crawl_time': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
                'total_time': 2.0,
                'total_price': 680,
                'transfers': 0,
                'details': [{
                    'type': 'flight', 'origin': origin, 'destination': destination,
                    'departure_time': '09:00', 'arrival_time': '11:00', 'price': 680
                }]
            }]
            return fallback
        print(f"📊 响应状态: {response.status_code}")
        
        if response.status_code == 200:
            result = response.json()
            print(f"�� 响应数据: {json.dumps(result, ensure_ascii=False)[:200]}...")
            
            if result.get('error_code') == 0:
                flights = []
                flight_list = result.get('result', {}).get('flightInfo', [])
                
                for item in flight_list:
                    try:
                        # 计算总时间（小时）
                        dep_time = item.get('departureTime', '')
                        arr_time = item.get('arrivalTime', '')
                        dep_date = item.get('departureDate', '')
                        arr_date = item.get('arrivalDate', '')
                        total_time = 2.0  # 默认2小时
                        try:
                            # 组装完整时间，例如 2025-09-20 07:30
                            dep_dt_str = f"{dep_date} {dep_time}".strip()
                            arr_dt_str = f"{arr_date} {arr_time}".strip()
                            from datetime import datetime as _dt
                            dep_dt = _dt.strptime(dep_dt_str, '%Y-%m-%d %H:%M')
                            arr_dt = _dt.strptime(arr_dt_str, '%Y-%m-%d %H:%M')
                            # 计算相差分钟（处理跨天）
                            if arr_dt < dep_dt:
                                # 少数数据可能日期未对齐，强制加一天
                                arr_dt = arr_dt.replace(day=arr_dt.day) + timedelta(days=1)
                            total_minutes = int((arr_dt - dep_dt).total_seconds() // 60)
                            total_time = max(0.5, round(total_minutes / 60.0, 1))
                        except Exception:
                            pass
                        
                        flight = {
                            'type': 'flight',
                            'flight_number': item.get('flightNo', ''),
                            'airline': item.get('airlineName', ''),
                            'origin': origin,
                            'destination': destination,
                            'dep_time': f"{item.get('departureDate', '')} {item.get('departureTime', '')}",
                            'arr_time': f"{item.get('arrivalDate', '')} {item.get('arrivalTime', '')}",
                            'price': int(item.get('ticketPrice', 0)),
                            'dep_airport': item.get('departureName', ''),
                            'arr_airport': item.get('arrivalName', ''),
                            'duration': f"{item.get('departureTime', '')} - {item.get('arrivalTime', '')}",
                            'source': '聚合数据API',
                            'crawl_time': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
                            # 前端期望字段
                            'total_time': total_time,
                            'total_price': int(item.get('ticketPrice', 0)),
                            'transfers': 0,
                            'details': [{
                                'type': 'flight',
                                'origin': origin,
                                'destination': destination,
                                'departure_time': f"{item.get('departureTime', '')}",
                                'arrival_time': f"{item.get('arrivalTime', '')}",
                                'price': int(item.get('ticketPrice', 0)),
                                'airline': item.get('airlineName', ''),
                                'flight_number': item.get('flightNo', '')
                            }]
                        }
                        
                        if flight['price'] > 0:
                            flights.append(flight)
                            
                    except Exception as e:
                        print(f"  ❌ 解析航班条目异常: {e}")
                        continue
                
                print(f"✅ 获取到 {len(flights)} 条机票数据")
                return flights
            else:
                print(f"❌ 机票API错误: {result.get('reason', '未知')}")
                return []
        else:
            print(f"❌ 机票API请求失败: {response.status_code}")
            return []
            
    except Exception as e:
        print(f"❌ 机票API异常: {e}")
        return []

class MyHTTPRequestHandler(http.server.SimpleHTTPRequestHandler):
    def __init__(self, *args, **kwargs):
        static_root = os.path.dirname(__file__)
        super().__init__(*args, directory=static_root, **kwargs)
    
    def do_OPTIONS(self):
        # 处理CORS预检
        self.send_response(200)
        self.send_header('Access-Control-Allow-Origin', '*')
        self.send_header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS')
        self.send_header('Access-Control-Allow-Headers', 'Content-Type')
        self.end_headers()
    
    def do_GET(self):
        if self.path == '/':
            self.path = '/frontend/index.html'
        elif self.path.startswith('/api/'):
            self.handle_api_request()
            return
        super().do_GET()
    
    def do_POST(self):
        if self.path == '/api/search':
            self.handle_search_request()
        elif self.path == '/api/poi':
            self.handle_poi_request()
        elif self.path == '/api/geocode':
            self.handle_geocode_request()
        elif self.path == '/api/chat':
            self.handle_chat_request()
        else:
            self.send_error(404)
    
    def handle_api_request(self):
        if self.path == '/api/status':
            self.send_api_status()
        elif self.path == '/api/cities':
            self.send_cities()
        elif self.path.startswith('/api/weather'):
            self.send_weather()
        else:
            self.send_error(404)
    
    def handle_search_request(self):
        content_length = int(self.headers.get('Content-Length', 0))
        post_data = self.rfile.read(content_length)
        
        try:
            data = json.loads(post_data.decode('utf-8'))
        except:
            data = {}
        
        origin = data.get('origin', '北京')
        destination = data.get('destination', '上海')
        date = data.get('date') or data.get('departure_date')
        optimization_type = data.get('optimization_type', 'time')
        
        print(f"🔍 搜索请求: {origin} → {destination} ({date})")
        
        all_routes = []
        
        # 获取机票数据
        flights = get_flight_data(origin, destination, date or '2025-09-20')
        all_routes.extend(flights)

        # 加载本地高铁数据（直达/一次中转）
        try:
            rail_routes = find_train_routes(origin, destination, date or '2025-09-20')
            all_routes.extend(rail_routes)
        except Exception as e:
            print(f"读取本地铁路数据失败: {e}")

        # 周边城市数据
        nearby_origins = NEARBY_CITIES.get(origin, [])
        nearby_destinations = NEARBY_CITIES.get(destination, [])
        
        # 周边出发城市
        for nearby_origin in nearby_origins[:2]:
            if nearby_origin not in CITY_TO_IATA:
                continue
            nearby_flights = get_flight_data(nearby_origin, destination, date or '2025-09-20')
            for flight in nearby_flights:
                flight['is_nearby'] = True
                flight['nearby_type'] = 'origin'
                flight['nearby_city'] = nearby_origin
                flight['origin'] = f"{nearby_origin}({origin}附近)"
            all_routes.extend(nearby_flights)
        
        # 周边到达城市
        for nearby_dest in nearby_destinations[:2]:
            if nearby_dest not in CITY_TO_IATA:
                continue
            nearby_flights = get_flight_data(origin, nearby_dest, date or '2025-09-20')
            for flight in nearby_flights:
                flight['is_nearby'] = True
                flight['nearby_type'] = 'destination'
                flight['nearby_city'] = nearby_dest
                flight['destination'] = f"{nearby_dest}({destination}附近)"
            all_routes.extend(nearby_flights)
        
        # 航班+高铁 联运方案（航班到附近城市 + 高铁至终点）
        try:
            intermodal = build_flight_rail_combos(destination, date or '2025-09-20', all_routes)
            all_routes.extend(intermodal)
        except Exception as e:
            print(f"联运构建失败: {e}")

        # 智能排序
        if optimization_type == 'price':
            all_routes.sort(key=lambda x: x.get('total_price') if x.get('total_price') is not None else x.get('price', 0))
        elif optimization_type == 'time':
            all_routes.sort(key=lambda x: x.get('total_time', 0))
        
        # 优先显示非周边城市的结果
        all_routes.sort(key=lambda x: x.get('is_nearby', False))
        
        # 统计信息
        flights_count = len([x for x in all_routes if x.get('type') == 'flight'])
        nearby_count = len([x for x in all_routes if x.get('is_nearby', False)])
        
        result = {
            'success': True,
            'routes': all_routes,
            'data': all_routes,
            'total': len(all_routes),
            'flights': flights_count,
            'trains': 0,
            'nearby': nearby_count,
            'optimization_type': optimization_type,
            'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        }
        
        print(f"✅ 搜索完成: 找到 {len(all_routes)} 条结果（航班 {flights_count}，周边 {nearby_count}）")
        self.send_json_response(result)
    
    def send_api_status(self):
        status = {
            'success': True,
            'status': 'success',
            'message': '最终版服务器运行正常',
            'version': '5.1.0',
            'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
            'features': [
                '真实机票数据获取（聚合数据API）',
                '周边城市智能对比',
                '智能排序和推荐',
                '完整静态文件服务',
                '天气/POI/地理编码/对话接口（轻量模拟）'
            ],
            'apis': {
                'flight': 'enabled',
                'nearby': 'enabled',
                'smart_sort': 'enabled',
                'weather': 'mock',
                'poi': 'mock',
                'geocode': 'mock',
                'chat': 'mock'
            },
            'nearby_cities': NEARBY_CITIES
        }
        self.send_json_response(status)
    
    def send_cities(self):
        # 前端回退检索期望对象形式：{ id, name, code?, level, full_name? }
        names = list(NEARBY_CITIES.keys())
        cities = [
            {
                'id': idx + 1,
                'name': name,
                'code': '',
                'level': 'city',
                'full_name': name
            }
            for idx, name in enumerate(names)
        ]
        self.send_json_response({'success': True, 'cities': cities})
    
    def send_weather(self):
        # 读取查询参数
        try:
            from urllib.parse import urlparse, parse_qs
            query = parse_qs(urlparse(self.path).query)
            city = (query.get('city') or ['北京'])[0]
        except Exception:
            city = '北京'
        # 返回轻量模拟数据（前端已有容错逻辑）
        data = {
            'success': True,
            'weather': {
                'weather': '晴',
                'temperature': 22,
                'humidity': 60,
                'wind_power': 3,
                'wind_direction': '东南风'
            },
            'city': city,
            'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        }
        self.send_json_response(data)
    
    def handle_poi_request(self):
        content_length = int(self.headers.get('Content-Length', 0))
        body = self.rfile.read(content_length) if content_length > 0 else b'{}'
        try:
            payload = json.loads(body.decode('utf-8'))
        except:
            payload = {}
        keyword = payload.get('keyword', '景点')
        city = payload.get('city', '北京')
        # 轻量模拟POI结果
        pois = [
            { 'id': '1', 'name': f'{city}{keyword}示例一', 'address': f'{city}中心区', 'location': '116.3974,39.9093', 'type': keyword },
            { 'id': '2', 'name': f'{city}{keyword}示例二', 'address': f'{city}热门商圈', 'location': '116.4053,39.9042', 'type': keyword },
            { 'id': '3', 'name': f'{city}{keyword}示例三', 'address': f'{city}特色街区', 'location': '116.4120,39.9200', 'type': keyword }
        ]
        self.send_json_response({ 'success': True, 'pois': pois })
    
    def handle_geocode_request(self):
        content_length = int(self.headers.get('Content-Length', 0))
        body = self.rfile.read(content_length) if content_length > 0 else b'{}'
        try:
            payload = json.loads(body.decode('utf-8'))
        except:
            payload = {}
        address = payload.get('address', '北京市东城区天安门')
        # 轻量模拟坐标（固定到天安门附近）
        coordinates = { 'lng': 116.3974, 'lat': 39.9093 }
        self.send_json_response({ 'success': True, 'address': address, 'coordinates': coordinates })
    
    def handle_chat_request(self):
        content_length = int(self.headers.get('Content-Length', 0))
        body = self.rfile.read(content_length) if content_length > 0 else b'{}'
        try:
            payload = json.loads(body.decode('utf-8'))
        except:
            payload = {}
        message = payload.get('message', '')
        # 非AI的简单回声/提示（前端已有意图识别与容错）
        reply = f"已收到：{message}。您也可以直接输入‘北京到上海’或‘查询北京天气’等指令哦。"
        self.send_json_response({ 'success': True, 'response': reply })
    
    def send_json_response(self, data):
        self.send_response(200)
        self.send_header('Content-type', 'application/json; charset=utf-8')
        self.send_header('Access-Control-Allow-Origin', '*')
        self.send_header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS')
        self.send_header('Access-Control-Allow-Headers', 'Content-Type')
        self.end_headers()
        
        json_data = json.dumps(data, ensure_ascii=False, indent=2)
        self.wfile.write(json_data.encode('utf-8'))

if __name__ == '__main__':
    PORT = 5000
    
    print("=" * 60)
    print("启动最终版HTTP服务器")
    print("=" * 60)
    print(f"服务地址: http://localhost:{PORT}")
    print(f"前端页面: http://localhost:{PORT}/frontend/index.html")
    print("=" * 60)
    print("按 Ctrl+C 停止服务")
    print("=" * 60)
    
    try:
        # 自动打开浏览器到前端页面
        try:
            webbrowser.open(f"http://localhost:{PORT}/frontend/index.html")
        except Exception:
            pass
        with socketserver.TCPServer(("", PORT), MyHTTPRequestHandler) as httpd:
            httpd.serve_forever()
    except KeyboardInterrupt:
        print("\n服务器已停止")
    except Exception as e:
        print(f"服务器启动失败: {e}")